<template>
	<view class="x-choose">

		<x-cell @click="show = true" :border="props.border">
			<template #icon>
				<slot name="icon"></slot>
			</template>

			<template #title>
				<view :style="{width: props.labelWidth}" class="x-row" style="position: relative;">
					<view style="width: 12rpx;color: red;position: absolute;left: -20rpx;top: 4rpx">
						<text v-if="props.required">*</text>
					</view>
					<view class="x-label">{{props.label}}</view>
				</view>
			</template>
			<template #value>
				<view class="control" :style="{width: 'calc(100% - ' + props.labelWidth + '})'}">
          <view v-if="! $emptyArray(showValue)">{{showValue.join(",")}}</view>
          <view v-else>{{props.placeholder}}</view>
				</view>
			</template>

			<template #suffix>
				<view style="min-width: 30rpx;">
					<slot name="suffix">
						<uni-icons color="#999" :type="props.suffixIcon"></uni-icons>
					</slot>
				</view>
			</template>
		</x-cell>
	</view>
  <x-popup v-model="show" title="请选择">
    <view @click="onCancel" class="cancel" slot="left">取消</view>
    <view @click="onConfirm" class="confirm" slot="right">确认</view>
    <view v-for="item in list">
      <x-cell @click="onClick(item)" :title="item.label">
        <template #value>
          <uni-icons v-if="curValue.indexOf(item.value) > -1" color="#ff8900" type="checkmarkempty" ></uni-icons>
        </template>
      </x-cell>
    </view>
  </x-popup>
</template>
<script>
	export default {
		options: {
			styleIsolation: 'shared'
		},
	}
</script>
<script setup name="x-choose">
import XPopup from '@/components/lib/popup'
	import {GlobalConfig, Msg} from 'core';
	const {
		appConfig
	} = GlobalConfig();
	const dict = appConfig.selectStore && appConfig.selectStore()
	import {
		Helper,
		Log
	} from "@/core";
	import XCell from '@/components/lib/cell';
import {
  reactive,
  ref,
  toRaw,
  watch
} from "vue";

	const props = defineProps({
		label: String,
		labelWidth: {
			type: String,
			default: "180rpx"
		},
		modelValue: [Array],
		placeholder: {
			type: String,
			default: "请选择"
		},
		textAlign: {
			type: String,
			default: 'right'
		},
		required: {
			type: Boolean,
			default: false,
		},
		suffixIcon: {
			type: String,
			default: "right",
		},
		options: {
			type: [Array, String],
		},
		disabled: {
			type: Boolean,
			default: false
		},
		border: {
			type: Boolean,
			default: true
		},
		type: {
			type: String,
			default: "dict"
		},
		count: {
			type: Number,
			default: -1
		},
		labelField: {
			type: [Array, String],
			default: "label",
		},

		valueField: {
			type: [Array, String],
			default: "value",
		},

		cache: {
			type: Boolean,
			default: false
		},

		query: {
			type: Object,
			default: () => {
				return {}
			}
		}
	})

	const emit = defineEmits([
		'update:modelValue',
		'onChange',
		'onClick'
	])

  const show = ref(false)
  const curValue = ref([]);
	const showValue = ref([])
	const list = ref([])
	const source = ref([])

	const setValue = (value) => {
		value = !Helper.emptyArray(value) ? value : [];
		clear();
		if (!Helper.emptyArray(list.value)) {
			let options = list.value.filter(x => value.indexOf(x.value) > -1);
			if(! Helper.emptyArray(options)) {
				showValue.value = options.map(x => x[props.labelField]);
			}
		}
    curValue.value = value;
	}

	const clear = () => {
		showValue.value = [];
    curValue.value = [];
	}

	const init = async (options) => {
		if (!options) {
			return;
		}
		let data = [];
		if (typeof options == 'string') {
			data = await loadByRemote(options, props.query, props.cache);
		} else {
			data = options;
		}

		if (Helper.emptyArray(data)) {
			// Log.error(options);
			data = [];
		}

		source.value = data;

		if (props.count > -1 && data.length > props.count) {
			data = data.slice(0, props.count);
		}

		list.value = optionFormat(data);

		if (props.count > -1 && source.value.length > props.count) {
			handleValue(curValue.value);
		}

		setValue(curValue.value)
	}

	const loadByRemote = async (options, query, cache) => {
		//todo 验证store是否存在
		if (Helper.empty(dict)) {
			Msg.error("未配置下拉框store，请先检查配置");
			return;
		}
		//todo 处理为字典表码情况
		if (props.type == 'dict') {
			if (!dict.get) {
				Msg.error("未在stores中实现获取字典表码的接口");
				return;
			}

			let data = await dict.get(options, query, cache);
			return data;
		}

		if (Helper.empty(dict[options])) {
			// Msg.error("未实现下拉框的" + options + "，请选实现");
			return;
		}

		let resp = [];
		if (typeof dict[options] == 'function') {
			resp = await dict[options](query, cache);
		} else {
			resp = await dict[options];
		}

		return resp;
	}

	const handleValue = (value) => {
		setTimeout(() => {
			let index = list.value.findIndex(item => value.indexOf(item[props.valueField]) > -1);
			if (index > -1) {
				return;
			}

			let options = source.value.filter(item => value.indexOf(item[props.valueField]) > -1);
			if (!Helper.emptyArray(options)) {
        options.forEach(option => {
          let res = convert(option);
          if (!Helper.empty(res)) {
            list.value.push(res);
          }
        })
			}
		}, 100)
	}

	const optionFormat = (options) => {
		let res = [];
		if (Array.isArray(options)) {
			options.forEach(i => {
				let item = convert(i);
				if (!Helper.empty(item)) {
					res.push(item);
				}
			})
		}

		return res;
	}

	const convert = (i) => {
		let config = {
			mapperValue: "value",
			mapperLabel: "label",
			enableField: false,
			labelField: props.labelField,
			valueField: props.valueField
		};
		let enableField = config.enableField;
		let item = Object.assign({}, i);
		let label = "";
		if (!enableField || i[enableField[0]] == enableField[1]) {
			if (!Array.isArray(config.labelField)) {
				label = i[config.labelField];
			} else {
				let labels = [];
				config.labelField.forEach(l => {
					let text = i[l];
					if (!Helper.empty(text)) {
						labels.push(text);
					}
				})

				label = labels.join("--")
			}

			item[config.mapperLabel] = label;
			item[config.mapperValue] = i[config.valueField];
			return item;
		}

		return null;
	}

	const onClick = (option) => {
	  let idx = curValue.value.indexOf(option.value);
	  if(idx > -1) {
      curValue.value.splice(idx, 1)
    } else {
      curValue.value.push(option.value);
    }
    emit("onChange", curValue.value, option)
	}

	const onCancel = () => {
	  clear();
	  show.value = false;
  }

  const onConfirm = () => {
    emit('update:modelValue', curValue.value)
    show.value = false;
  }

	watch(() => props.modelValue, (value) => {
		setValue(value)
	},{immediate: true})

	// 不知道为什么加了immediate会报错。后置解决
	watch(() => props.options, (value) => {
		if(Helper.empty(value)) {
			return;
		}
		init(value)
	}, {immediate: true})
</script>

<style scoped lang="less">
	.x-row {
		display: flex;
		flex-direction: row;
		align-items: center;
	}

	.control {
    font-size: 28rpx;
		input {
			width: 100%;
			// padding-right: 0 !important;
		}
	}

  .overflow {
    white-space: nowrap;
    text-overflow: ellipsis;
    -o-text-overflow: ellipsis;
    width: 100%;
  }

  .cancel{
    color: #999999;
    font-size: 28rpx;
  }

  .confirm {
    color: @primary;
    font-size: 28rpx;
  }
</style>
